<script setup lang="ts">
import type { IUploadResult } from '@/api/interface/system/admin/upload'
import { computed, ref, watch } from 'vue'
import { uploadFile, uploadToOssWithPreSignedUrl } from '@/api/modules/system/admin/upload'

interface UploadFileProps {
  imageUrl?: string // 单图片地址 (兼容旧版本)
  fileList?: Array<{ name: string; url: string }> // 图片列表
  disabled?: boolean // 是否禁用上传组件
  fileSize?: number // 图片大小限制 (MB)
  height?: string // 组件高度
  width?: string // 组件宽度
  borderRadius?: string // 组件边框圆角
  dir?: string // 上传图片的目录
  useOss?: boolean // 是否使用OSS直传
  limit?: number // 最大上传数量
  title?: string // 标题
  accept?: string // 接受的文件类型
  multiple?: boolean // 是否支持多选文件
  beforeUpload?: (file: UniApp.ChooseImageSuccessCallbackResultFile) => boolean | Promise<boolean>
}

const props = withDefaults(defineProps<UploadFileProps>(), {
  imageUrl: '',
  fileList: () => [],
  disabled: false,
  height: '150px',
  width: '150px',
  limit: 1,
  fileSize: 5,
  title: '上传图片',
  accept: 'image/*',
  multiple: true,
  beforeUpload: () => true,
  dir: 'default',
  useOss: true,
})

const emit = defineEmits<{
  'update:imageUrl': [value: string]
  'update:fileList': [value: Array<{ name: string; url: string }>]
  change: [value: IUploadResult]
}>()

// 响应式数据
const innerFileList = ref<Array<{ name: string; url: string }>>([])
const showProgress = ref(false)
const uploadProgress = ref(0)

// 计算fileList，同时兼容单图片和多图片模式
const fileList = computed<Array<{ name: string; url: string }>>({
  get: () => {
    // 优先使用props.fileList
    if (props.fileList && props.fileList.length > 0) {
      return props.fileList
    }
    // 兼容旧版单图片模式
    if (props.imageUrl) {
      return [
        {
          name: props.imageUrl.split('/').pop() || 'image.jpg',
          url: props.imageUrl,
        },
      ]
    }
    return innerFileList.value
  },
  set: (val) => {
    innerFileList.value = val
    emit('update:fileList', val)
    // 兼容旧版单图片模式
    if (val.length > 0) {
      emit('update:imageUrl', val[0].url || '')
    } else {
      emit('update:imageUrl', '')
    }
  },
})

// 选择图片
function chooseImage() {
  if (props.disabled) return

  // 检查上传数量限制
  if (props.limit > 0 && fileList.value.length >= props.limit) {
    uni.showToast({
      title: `最多只能上传 ${props.limit} 张图片`,
      icon: 'none',
    })
    return
  }

  uni.chooseImage({
    count: props.multiple ? props.limit - fileList.value.length : 1,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success: (res) => {
      handleImageUpload(res.tempFiles as UniApp.ChooseImageSuccessCallbackResultFile[])
    },
    fail: (error) => {
      console.error('选择图片失败:', error)
      uni.showToast({
        title: '选择图片失败',
        icon: 'none',
      })
    },
  })
}

// 处理图片上传
async function handleImageUpload(tempFiles: UniApp.ChooseImageSuccessCallbackResultFile[]) {
  showProgress.value = true
  uploadProgress.value = 0

  try {
    for (const file of tempFiles) {
      // 文件大小检查
      const fileSizeMB = file.size / 1024 / 1024
      if (fileSizeMB > props.fileSize) {
        uni.showToast({
          title: `图片大小不能超过 ${props.fileSize}MB`,
          icon: 'none',
        })
        continue
      }

      // 自定义上传前检查
      if (props.beforeUpload) {
        const shouldUpload = await props.beforeUpload(file)
        if (!shouldUpload) continue
      }

      // 上传文件
      if (props.useOss) {
        // 使用OSS直传
        await uploadToOssWithPreSignedUrl(
          file as any,
          `image_${Date.now()}.jpg`,
          props.dir,
          (percent) => {
            uploadProgress.value = percent
          },
          (result) => {
            // 添加到文件列表
            const newFile = {
              name: file.path?.split('/').pop() || `image_${Date.now()}.jpg`,
              url: result.url,
            }
            const newFileList = [...fileList.value, newFile]
            fileList.value = newFileList

            // 触发change事件
            emit('change', result)

            uni.showToast({
              title: '上传成功',
              icon: 'success',
            })
          },
          (error) => {
            uni.showToast({
              title: error.message || '上传失败',
              icon: 'none',
            })
          },
        )
      } else {
        // 使用服务器上传
        const { data } = await uploadFile({ file, dirTag: props.dir })

        // 添加到文件列表
        const newFile = {
          name: `image_${Date.now()}.jpg`,
          url: data.url,
        }
        const newFileList = [...fileList.value, newFile]
        fileList.value = newFileList

        emit('change', data)

        uni.showToast({
          title: '上传成功',
          icon: 'success',
        })
      }
    }
  } catch (error) {
    console.error('上传失败:', error)
    uni.showToast({
      title: '上传失败',
      icon: 'none',
    })
  } finally {
    showProgress.value = false
    uploadProgress.value = 0
  }
}

// 删除图片
function deleteImage(index: number) {
  uni.showModal({
    title: '提示',
    content: '确定要删除这张图片吗？',
    success: (res) => {
      if (res.confirm) {
        const newFileList = [...fileList.value]
        newFileList.splice(index, 1)
        fileList.value = newFileList

        uni.showToast({
          title: '删除成功',
          icon: 'success',
        })
      }
    },
  })
}

// 预览图片
function previewImage(url: string) {
  if (!url) return

  const urls = fileList.value.map((item) => item.url).filter(Boolean)
  const current = urls.indexOf(url)

  uni.previewImage({
    urls,
    current: current >= 0 ? current : 0,
  })
}

// 监听外部fileList变化
watch(
  () => props.fileList,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      innerFileList.value = [...newVal]
    }
  },
  { immediate: true, deep: true },
)
</script>

<template>
  <view class="upload-img">
    <!-- 已上传图片列表 -->
    <view v-if="fileList.length > 0" class="image-list">
      <view
        v-for="(item, index) in fileList"
        :key="index"
        class="image-item"
        :style="{ width, height }"
      >
        <image
          :src="item.url || ''"
          class="upload-image"
          mode="aspectFill"
          @click="previewImage(item.url || '')"
        />

        <!-- 操作按钮 -->
        <view v-if="!disabled" class="image-actions">
          <view class="action-btn delete-btn" @click.stop="deleteImage(index)">
            <wd-icon name="delete" size="16" color="#fff" />
          </view>
          <view class="action-btn preview-btn" @click.stop="previewImage(item.url || '')">
            <wd-icon name="eye" size="16" color="#fff" />
          </view>
        </view>
      </view>
    </view>

    <!-- 上传按钮 -->
    <view
      v-if="fileList.length < limit || limit === 0"
      class="upload-btn"
      :class="{ disabled }"
      :style="{ width, height }"
      @click="chooseImage"
    >
      <slot name="empty">
        <view class="upload-content">
          <wd-icon name="plus" size="24" color="#999" />
          <text class="upload-text">点击上传</text>
        </view>
      </slot>
    </view>

    <!-- 提示文字 -->
    <view v-if="$slots.tip" class="upload-tip">
      <slot name="tip" />
    </view>

    <!-- 上传进度 -->
    <wd-popup v-model="showProgress" position="center" class="progress-popup">
      <view class="progress-content">
        <wd-loading size="large" />
        <text class="progress-text">上传中... {{ uploadProgress }}%</text>
      </view>
    </wd-popup>
  </view>
</template>

<style scoped lang="scss">
.upload-img {
  .image-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 12px;

    .image-item {
      position: relative;
      border-radius: 12px;
      overflow: hidden;
      border: none;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);

      &:active {
        transform: scale(0.95);
        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
      }

      .upload-image {
        width: 100%;
        height: 100%;
        display: block;
        transition: transform 0.3s ease;
      }

      .image-actions {
        position: absolute;
        top: 8px;
        right: 8px;
        display: flex;
        gap: 8px;
        opacity: 0;
        transform: translateY(-8px);
        transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);

        .action-btn {
          width: 28px;
          height: 28px;
          border-radius: 14px;
          display: flex;
          align-items: center;
          justify-content: center;
          backdrop-filter: blur(20px);
          transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
          border: 1px solid rgba(255, 255, 255, 0.3);

          &:active {
            transform: scale(0.9);
          }

          &.delete-btn {
            background: rgba(255, 59, 48, 0.9);
            box-shadow: 0 2px 8px rgba(255, 59, 48, 0.3);
          }

          &.preview-btn {
            background: rgba(0, 122, 255, 0.9);
            box-shadow: 0 2px 8px rgba(0, 122, 255, 0.3);
          }
        }
      }

      // 移动端显示操作按钮
      &:active .image-actions,
      &:hover .image-actions {
        opacity: 1;
        transform: translateY(0);
      }

      // 为移动端添加长按效果
      @media (hover: none) {
        .image-actions {
          opacity: 1;
          transform: translateY(0);
          top: auto;
          bottom: 8px;
          background: rgba(0, 0, 0, 0.7);
          padding: 8px;
          border-radius: 20px;
          backdrop-filter: blur(10px);
        }
      }
    }
  }

  .upload-btn {
    border: 2px dashed #e5e5ea;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    background: #f2f2f7;

    &:active {
      border-color: #007aff;
      background: rgba(0, 122, 255, 0.05);
      transform: scale(0.98);
    }

    &.disabled {
      opacity: 0.5;
      border-color: #f2f2f7;
      background: #f9f9f9;

      &:active {
        border-color: #f2f2f7;
        background: #f9f9f9;
        transform: none;
      }

      .upload-content {
        .upload-text {
          color: #c7c7cc;
        }
      }
    }

    .upload-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;
      padding: 16px;

      .upload-text {
        font-size: 15px;
        color: #8e8e93;
        font-weight: 500;
        letter-spacing: -0.24px;
      }
    }
  }

  .upload-tip {
    margin-top: 12px;
    font-size: 13px;
    color: #8e8e93;
    text-align: center;
    line-height: 1.4;
    letter-spacing: -0.08px;
  }
}

// Apple风格的进度弹窗
.progress-popup {
  .progress-content {
    padding: 32px 24px;
    text-align: center;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(20px);
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);

    .progress-text {
      margin-top: 16px;
      font-size: 15px;
      color: #1d1d1f;
      font-weight: 500;
      letter-spacing: -0.24px;
    }
  }
}

// 通用Apple风格动画
.upload-img {
  -webkit-tap-highlight-color: transparent;
}
</style>
